(堆)内存释放 & (栈)作用域销毁 & 作用域销毁实战题

堆栈

(堆)内存释放

  • [ ] 不能销毁的情况:堆内存地址被外界变量引用时
    • 对象数据类型或者函数数据类型在定义时,会开辟一个堆内存,这个堆内存有一个引用的地址,如果外面有变量接收这个地址,这个内存就被占用了,因此不能销毁;
  • [ ] 把引用内存地址的变量=null来销毁
    • 当内存地址不被引用了,那么浏览器会在空闲时销毁这个堆内存;

-

  • 以下面代码为例
    1
    2
    3
    4
    5
    6
    7
    //对象或者函数类型(obj1)在定义时,开辟一个堆内存
    var obj1={name:"张三"};
    //(obj1的堆地址)被(obj2)引用
    var obj2=obj1;
    //通过(=null)来销毁
    obj1=null;
    obj2=null;//如果只清除obj2,那么obj1内存仍存在,视浏览器清除机制而定;

其图形分析为图20

对于内存谷歌、IE、火狐不同浏览器的处理技巧
谷歌定时主动清除当前页面中不被占用的内存;
IE、火狐计数器原理,当被占用数=0时,清除该内存;

  • 当计数计晕了时,产生内存泄漏问题

(栈)作用域销毁

全局作用域(只有页面关闭才会销毁)

私有作用域(只有函数执行才会产生私有作用域)

1
2
3
for(){
}//不是私有作用域,只是代码块

(1)一般情况下,函数执行产生新的私有作用域,执行完毕会主动释放和销毁;

(2)特殊情况下,当前私有作用域部分内存被作用域以外的占用,则当前内存不能销毁,(分下面三种情况)

  • [x] 1、 (不销毁)–函数执行返回引用数据类型、且在函数外被接收

    (原理就是堆内存被占有,其地盘也不能销毁)
    
    • 以下面代码为例

      1
      2
      3
      4
      5
      6
      7
      8
      var num=12;
      function fn(){
      var num=120;
      return function(){
      …………
      };
      }
      var f=fn();////fn执行时形成的私有作用域不销毁

    图形分析21

  • [x] 2、 (不销毁)- -在一个私有作用于下给DOM元素绑定事件,这种情况一般不销毁私有作用域

    • 以下面代码为例

      1
      2
      3
      4
      5
      var oDiv=document.getElementById("div");
      ~function (){
      oDiv.onclick=function(){
      }
      }();//自执行函数形成的私有作用域不销毁

图形分析22

  • [x] 3、 (不立即销毁) fn()()–fn返回的函数没被占用,但是还需要执行一次,所以暂时不销毁,待返回的值执行完后浏览器会在空闲的时候把它销毁;

    • 以下面代码为例

      1
      2
      3
      4
      5
      6
      function fn(){
      var num=100;
      return function(){
      };
      };
      fn()();//先执行fn(),返回一个对应的内存地址,然后紧接着执行返回的小函数

作用域销毁实战题

小知识点

1
2
3
4
var i=5;
//每运算一小步,i的值都会变
alert(2+(i++)+(++i)+(++i)+(i++));//-->30;
//运算完2+(i++)后i=6

  • 以下面代码为例1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function fn(){
    var i=10;
    return function(n){
    console.log(n+(++i));
    }
    }
    //函数执行每次跟每次都没关系
    var f=fn();
    //f的上级作用域是fn()A作用域--不销毁
    f(10); //10+11=21;
    f(20); //20+12=32;
    //此时fn()()的上级作用域是fn()B作用域--在fn()()执行前暂时不销毁
    fn()(10); //10+11=21
    //此时fn()()的上级作用域是fn()C作用域--在fn()()执行前暂时不销毁
    fn()(20); //20+11=31

分析图形23

  • 以下面代码为例2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function fn(i){
    return function(n){
    console.log(n+(i++));
    }
    }
    var f=fn(13); //i=13
    f(12); //i=13 12+13=25 i=14
    f(14); //i=14 14+14=28 i=15
    fn(15)(12); //i=15 12+15=27 i=16
    fn(16)(13); //i=16 13+16=29 i=17

    思考题:用闭包作用域的方式,实现选项卡循环绑定事件的处理